home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
9-Digit Zip Code Directory
/
9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO
/
z4src.zip
/
Z4CSFILE.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-19
|
15KB
|
468 lines
//----------------------------------------------------------------------------
// MODULE DESCRIPTION
//
// Module: z4csfile.cpp
// Title: ZIP+4 Engine
// Notice: John M. Weeder
// Copyright (c) 1993. All rights reserved.
// This module contains proprietary information and should be
// treated as confidential.
//
//----------------------------------------------------------------------------
// MAINTENANCE HISTORY
//
// $Workfile$
// $Revision$
// $Author$
// $Date$
// $Log$
//
//----------------------------------------------------------------------------
// MODULE NARRATIVE
//
// This module contains code for the class Z4_CS_FILE.
//
// The code in this module may be written in C++ or C.
//
// This module is portable to:
// DOS 3.X+
// MS Windows 3.X+
// OS/2 2.X+
// OS/2 2.0 PM
//
// The following compilers are supported:
// MSC 6.0A
// MSC/C++ 7.0
// Borland C++ 3.1 for DOS
// Borland C++ 1.0 for OS/2 2.X
//
//----------------------------------------------------------------------------
#include <z4.h>
//----------------------------------------------------------------------------
// Globals
//----------------------------------------------------------------------------
PCSZ Z4_CS_FILE::pcszLogical = "City/State";
//----------------------------------------------------------------------------
// Description: Default constructor
// Parameters:
// Returns:
//----------------------------------------------------------------------------
FN_M Z4_CS_FILE::Z4_CS_FILE()
{
Z4_CS_FILE::Initialize(CL_INIT_CLASS);
}
//----------------------------------------------------------------------------
// Description: Copy constructor
// Parameters: rcz4_cs_file Reference to object to copy.
// Returns:
//----------------------------------------------------------------------------
FN_M Z4_CS_FILE::Z4_CS_FILE(RCZ4_CS_FILE rcz4_cs_file)
{
Z4_CS_FILE::Initialize(CL_INIT_CLASS);
*this = rcz4_cs_file;
}
//----------------------------------------------------------------------------
// Description: Destructor
// Parameters:
// Returns:
//----------------------------------------------------------------------------
FN_M Z4_CS_FILE::~Z4_CS_FILE()
{
Z4_CS_FILE::Destroy(FALSE);
}
//----------------------------------------------------------------------------
// Description: Find the best city record for a given five digit ZIP record.
// Selects the matching last line number with the highest
// facility code.
// Parameters:
// Returns: TRUE if valid
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::Best(RZ4_CS rz4_cs, RZ4_Z5 rz4_z5, PCSZ pcszLastLine)
{
if (IsError()) // Check error condition
return FALSE;
if (pcszLastLine == NULL || strlen(pcszLastLine) != MAX_LAST_LINE)
pcszLastLine = "000000";
SIZET iBest, iCur;
Z4_FACILITY facility = Z4_FACILITY_OTHER;
BOOL fLastLine = FALSE;
Assert(rz4_z5.cCities);
for (SIZET i = 0; i < rz4_z5.cCities; ++i)
{
if (!Record(rz4_cs, rz4_z5.arecid[i]))
return FALSE;
iCur = i;
BOOL fLastLineCur = stricmp(pcszLastLine, rz4_cs.szLastLine) == 0;
if (i == 0
|| (!fLastLine && (fLastLineCur || rz4_cs.facility > facility))
|| (fLastLine && fLastLineCur && rz4_cs.facility > facility))
{
iBest = i;
facility = rz4_cs.facility;
fLastLine = fLastLineCur;
if (fLastLineCur && rz4_cs.facility == Z4_FACILITY_PO)
break;
}
}
// Read best record
if (iCur != iBest && !Record(rz4_cs, rz4_z5.arecid[iBest]))
return FALSE;
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Destroy object. Free any resources used by object.
// Normally called by destructor.
// Should allow multiple calls from various classes.
// Parameters: fDestroyAll Destroy parents also?
// Default is TRUE.
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::Destroy(BOOL fDestroyAll)
{
DioCloseLogical(hlf);
DioCloseLogical(hlfRecNo);
Z4CSExpandTerminate(&z4_cs_blk);
Z4_CS_FILE::Initialize(CL_INIT_CLASS_VARS);
if (fDestroyAll) // Destroy parent.
Z4_CS_FILE_PARENT::Destroy(fDestroyAll);
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Find first record in a specified block.
// Parameters: z4_cs Buffer for record
// state State code.
// pcszCity City name or NULL.
// Default is NULL.
// Returns: TRUE if valid
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::Find(RZ4_CS rz4_cs, Z4_STATE state, PCSZ pcszCity)
{
if (IsError()) // Check error condition
return FALSE;
Assert(pcszCity && state != Z4_ST_INVALID);
if (!First(rz4_cs, state, pcszCity))
return FALSE;
// SHORT sResult; org code
INT sResult;
do
{
sResult = stricmp(rz4_cs.szCity, pcszCity);
if (sResult == 0 && rz4_cs.state == state)
return TRUE;
}
while (rz4_cs.state == state && sResult < 0 && Next(rz4_cs));
return FALSE;
}
//----------------------------------------------------------------------------
// Description: Find first record in a specified block.
// Parameters: z4_cs Buffer for record
// state State code.
// pcszCity City name or NULL.
// Default is NULL.
// Returns: TRUE if valid
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::First(RZ4_CS rz4_cs, Z4_STATE state, PCSZ pcszCity)
{
if (IsError()) // Check error condition
return FALSE;
BYTE bKey[MAX_CS_KEY];
Z4CSKey(bKey, state, pcszCity);
LONG lIndexBlock;
if (!DioReadIndex(hlf, bKey, sizeof(bKey), &lIndexBlock))
return SetError();
if (First(rz4_cs, lIndexBlock))
{
do
{
BYTE bKey2[MAX_CX_KEY];
Z4CXKey(bKey2, rz4_cs.state, rz4_cs.szCity);
if (memcmp(bKey2, bKey, MAX_CS_KEY) >= 0)
return TRUE;
}
while (Next(rz4_cs));
return !IsError();
}
return FALSE;
}
//----------------------------------------------------------------------------
// Description: Find first record in a specified block.
// Parameters: z4_cs Buffer for record
// _lBlock Block to read
// Default is 0.
// Returns: TRUE if valid
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::First(RZ4_CS rz4_cs, LONG _lBlock)
{
if (IsError()) // Check error condition
return FALSE;
if (_lBlock >= lBlocks) // End of file!
return FALSE;
if (!fBlock || lBlock != _lBlock)
{
lBlock = _lBlock;
fBlock = TRUE;
fOffset = FALSE;
if (!DioSeekBlock(hlf, lBlock)
|| !DioReadBlock(hlf, NULL, &pb, NULL)
|| !Z4CSExpandReset(&z4_cs_blk, pb, (SIZET)usBlockSize))
return SetError();
}
if (fOffset && usOffset == 0)
{
rz4_cs = z4_cs_blk.cs; // Record was the existing expanded
return TRUE; // record
}
if (fOffset) // Reset expander for current block
if (!Z4CSExpandReset(&z4_cs_blk, pb, (SIZET)usBlockSize))
return SetError();
// Expand first record
if (!Z4CSExpand(&z4_cs_blk, &rz4_cs))
return SetError();
fOffset = TRUE;
usOffset = 0;
rz4_cs.recid.lBlock = lBlock;
rz4_cs.recid.usOffset = usOffset;
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Initialize object.
// Normally called by constructor.
// Should allow multiple calls from various classes.
// Parameters: sInit Initialization code. May be one of the following:
// CL_INIT_CLASS Reset class variables and
// and dynamic allocations for
// this class only.
// CL_INIT_CLASS_VARS Reset class variables for
// this class only.
// CL_INIT_VARS Reset class variables for
// this class only.
// CL_INIT_ALL Initialize class and all
// parent class, including
// dynamic memory allocation.
// Default is CL_INIT_ALL
// Returns: TRUE if successful.
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::Initialize(SHORT sInit)
{
if (sInit == CL_INIT_VARS || sInit == CL_INIT_ALL)
Z4_CS_FILE_PARENT::Initialize(sInit);
hlf = -1;
hlfRecNo = -1;
lRecs = -1;
memset(&z4_cs_blk, 0, sizeof(z4_cs_blk));
fBlock = FALSE;
fOffset = FALSE;
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Check if object is in error state.
// IsValid() && IsError() MUST NOT BE DEPENDENT ON ONE ANOTHER.
// Parameters:
// Returns: TRUE if in error state.
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::IsError() const
{
return Z4_CS_FILE_PARENT::IsError()
|| DioIsError(hlf)
|| DioIsError(hlfRecNo);
}
//----------------------------------------------------------------------------
// Description: Check if object is valid
// IsValid() && IsError() MUST NOT BE DEPENDENT ON ONE ANOTHER.
// Parameters:
// Returns: TRUE if valid
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::IsValid() const
{
return Z4_CS_FILE_PARENT::IsValid()
&& DioIsValid(hlf)
&& DioIsValid(hlfRecNo);
}
//----------------------------------------------------------------------------
// Description: Read next record
// Parameters: z4_cs Buffer for record
// Returns: TRUE if record found. FALSE if at end of file.
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::Next(RZ4_CS rz4_cs)
{
if (IsError()) // Check error condition
return FALSE;
Assert(fBlock && fOffset);
// Expand next record or goto next block
if (!Z4CSExpand(&z4_cs_blk, &rz4_cs))
return First(rz4_cs, lBlock + 1);
usOffset++;
rz4_cs.recid.lBlock = lBlock;
rz4_cs.recid.usOffset = usOffset;
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Open CS file
// Parameters:
// Returns: TRUE if valid
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::Open()
{
if (!Z4_INQ::Start()
|| !DioOpenIndex(pcszLogical, &hlf)
|| !DioCacheSet(hlf, 1)
|| !DioGetRecords(hlf, &lRecs)
|| !DioGetBlockSize(hlf, &usBlockSize)
|| !DioGetBlocks(hlf, &lBlocks)
|| !DioOpenRecNo(pcszLogical, &hlfRecNo)
|| !Z4CSExpandInitialize(&z4_cs_blk))
return SetError();
return TRUE;
}
//----------------------------------------------------------------------------
// Description: Assignment operator
// NOTE: Don't copy object into self
// Parameters: rcz4_cs_file Reference to right value.
// Returns: Reference to new object.
//----------------------------------------------------------------------------
RCZ4_CS_FILE FN_M Z4_CS_FILE::operator=(RCZ4_CS_FILE rcz4_cs_file)
{
if (this != &rcz4_cs_file)
{
Invalid("Z4_CS_FILE::operator=");
}
return (RCZ4_CS_FILE)*this;
}
//----------------------------------------------------------------------------
// Description: Read a particular record from the file
// Parameters: z4_cs Buffer for record
// lRec Record to read.
// If < 0, return current record
// Default is -1.
// Returns: TRUE if record found. FALSE if at end of file.
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::Record(RZ4_CS rz4_cs, LONG lRec)
{
RECID recid;
if (IsError()) // Check error condition
return FALSE;
if (lRec >= lRecs)
return FALSE;
if (lRec < 0) // Return current record
{
if (fBlock && fOffset)
{
rz4_cs = z4_cs_blk.cs;
return TRUE;
}
return FALSE;
} // Convert to record id
if (!DioRecNo2RecId(hlfRecNo, lRec, &recid))
return SetError();
return Record(rz4_cs, recid);
}
//----------------------------------------------------------------------------
// Description: Read a particular record from the file by record id
// Parameters: z4_cs Buffer for record
// recid Record id to read.
// Returns: TRUE if record found. FALSE if at end of file.
//----------------------------------------------------------------------------
BOOL FN_M Z4_CS_FILE::Record(RZ4_CS rz4_cs, RECID recid)
{
if (IsError()) // Check error condition
return FALSE;
// Move to correct block
if (!fBlock || recid.lBlock != lBlock)
if (!First(rz4_cs, recid.lBlock))
return FALSE;
if (recid.usOffset < usOffset) // If past desired record, restart
{ // from offset 0
if (!Z4CSExpandReset(&z4_cs_blk, pb, (SIZET)usBlockSize)
|| !Z4CSExpand(&z4_cs_blk, &rz4_cs))
return SetError();
usOffset = 0;
fOffset = TRUE;
}
rz4_cs = z4_cs_blk.cs; // Search for desired record
for (; usOffset < recid.usOffset; usOffset++)
if (!Z4CSExpand(&z4_cs_blk, &rz4_cs))
return SetError();
rz4_cs.recid.lBlock = lBlock;
rz4_cs.recid.usOffset = usOffset;
return TRUE;
}
//----------------------------------------------------------------------------
// Description:
// Parameters:
// Returns: Record number of current record or -1
//----------------------------------------------------------------------------
LONG FN_M Z4_CS_FILE::RecordNo()
{
if (IsError()) // Check error condition
return -1;
RECID recid;
recid.usOffset = usOffset;
recid.lBlock = lBlock;
LONG lRec;
if (!DioRecId2RecNo(hlfRecNo, &lRec, &recid))
{
SetError();
return -1;
}
return lRec;
}
//----------------------------------------------------------------------------
//------------------------------- End of File --------------------------------
//----------------------------------------------------------------------------